home *** CD-ROM | disk | FTP | other *** search
- /*************************************
- * *
- * LINEAR & NONLINEAR VARIANCE *
- * TEST PROGRAM *
- * *
- * M.E. Brandt, Ph.D. *
- * 02/06/91 Revision *
- * *
- *************************************/
-
- #include <stdio.h>
- #include <math.h>
- #include <malloc.h>
-
-
- #define NMAX 1024
- #define NBINS 10
- #define MAX_DELAY 30
- #define MAXRAND 32767.0
- #define DBL_LEN sizeof(double)
- #define PI 3.141592653589793
- #define TWOPI (2.0 * PI)
-
-
-
- double linvar(double *y, double *x, int nn);
- double nonlinvar(double *x, double *y, int n, int nbins);
- int number_bins(int x);
- void estimate_delay(double *x, double *y, int n);
-
-
-
- main()
- {
-
- int xx, i, j, nb, n, ch;
-
- double *x, *y, scale, r2, h2, start,
- noise, gain, a, inc, mean, num;
-
- char u[3], c;
-
-
-
- srand(1);
-
-
- /* SELECT A FUNCTION TO TEST */
-
- do {
-
- printf("\n\nSelect a y vs. x function and ");
- printf("compute variances:\n");
- printf("\n1. y = ax + noise (linear)");
- printf("\n2. y = sin(x) + noise");
- printf("\n3. y = sgn(x)*(x*x) + noise");
- printf("\n4. y = pow(3*x, 3) + noise");
- printf("\n5. y = pow(5*x, 5) + noise");
- printf("\n6. Exit");
- printf("\n\nSelect 1-6: ");
- scanf("%d", &ch);
-
- if(ch == 6) exit(0);
-
- do {
-
- printf("\n\nHow many data points?: ");
- scanf("%d", &n);
- }
- while(n > NMAX);
-
- do {
-
- printf("\n\nEnter noise gain: ");
- scanf("%lf", &gain);
- }
- while(gain < 0.0 || gain > 1.0);
-
- /* allocate space for x and y vectors */
-
- if((x = (double *)malloc(n * DBL_LEN)) == NULL) {
- fprintf(stderr, "\nMalloc error; x\n");
- exit(1);
- }
-
- if((y = (double *)malloc(n * DBL_LEN)) == NULL) {
- fprintf(stderr, "\nMalloc error; y\n");
- exit(1);
- }
-
-
- /* generate a random uniformly distributed x[n]
- between + or - 0.5
- */
-
- for(i=0; i<n; i++) x[i] =
- ((double)rand()/MAXRAND - 0.5);
-
-
- /* choose y[n] */
-
- switch(ch) {
-
- case 1: printf("\nEnter a: ");
- scanf("%lf", &a);
-
- for(i=0; i<n; i++) {
- noise = gain *
- ((double)rand()/MAXRAND - 0.5);
- y[i] = a * x[i] + noise;
- }
- break;
-
- case 2: for(i=0; i<n; i++) {
- noise = gain *
- ((double)rand()/MAXRAND - 0.5);
- y[i] = sin(TWOPI * x[i]) + noise;
- }
- break;
-
- case 3: for(i=0; i<n; i++) {
- noise = gain *
- ((double)rand()/MAXRAND - 0.5);
- y[i] = (x[i] * x[i]);
- if(x[i] < 0.0) y[i] *= -1.0;
- y[i] += noise;
- }
- break;
-
- case 4: for(i=0; i<n; i++) {
- noise = gain *
- ((double)rand()/MAXRAND - 0.5);
- y[i] = pow(3.0*x[i], 3.0) + noise;
- }
- break;
-
- case 5: for(i=0; i<n; i++) {
- noise = gain *
- ((double)rand()/MAXRAND - 0.5);
- y[i] = pow(5.0*x[i], 5.0) + noise;
- }
- break;
-
- default: break;
-
- }
-
- printf("\nTest delay estimation <y/n>?: ");
- scanf("%s", u);
- c = toupper(*u);
- if(c == 'Y') {
- estimate_delay(x, y, n);
- continue;
- }
-
-
-
- /* compute linear variance of x vs. y */
-
- r2 = linvar(x, y, n);
-
- printf("\nLinear r2(x,y) = %f\n", r2);
-
-
- /* choose number of bins */
-
- nb = number_bins(n);
-
- /* compute nonlinear variance of x vs. y */
-
- h2 = nonlinvar(x, y, n, nb);
-
- printf("\nNonlinear h2(x,y) = %f\n", h2);
-
-
- /* y vs. x */
-
- r2 = linvar(y, x, n);
-
- printf("\nLinear r2(y,x) = %f\n", r2);
-
-
- h2 = nonlinvar(y, x, n, nb);
-
- printf("\nNonlinear h2(y,x) = %f\n", h2);
-
- free(x); free(y);
-
- }
- while(1);
-
-
- }
-
-
-
-
-
-
-
- /* routine to find variances & delay between 2 lagged
- signals */
-
- double buf[NMAX+MAX_DELAY], r2[MAX_DELAY+10],
- h2[MAX_DELAY+10];
-
- void estimate_delay(double *x, double *y, int n)
- {
-
- int i, j, d, delay, lag, max_lag, np, nb;
-
- double max;
-
-
- do {
-
- printf("\nEnter delay between x and y in samples: ");
- scanf("%d", &delay);
- }
- while((d = abs(delay)) > MAX_DELAY);
-
-
- for(i=0; i<d; i++)
- buf[i] = ((double)rand()/MAXRAND - 0.5);
-
- max_lag = d + 10;
-
- if(delay > 0) { /* y lags x */
-
- /* move y to buf */
-
- for(j=0, i=d; j<n; i++, j++) buf[i] = y[j];
-
- for(lag=0; lag<max_lag; lag++) {
-
- np = n - lag; /* compute across less points */
-
- /* get linear variance at lag */
-
- r2[lag] = linvar(x, &buf[lag], np);
-
- nb = number_bins(np);
-
- /* get nonlinear variance at lag */
-
- h2[lag] = nonlinvar(x, &buf[lag], np, nb);
-
- }
-
- }
-
- else if(delay < 0) { /* x lags y */
-
- for(j=0, i=d; j<n; i++, j++) buf[i] = x[j];
-
- for(lag=0; lag<max_lag; lag++) {
-
- np = n - lag;
-
- r2[lag] = linvar(&buf[lag], y, np);
-
- nb = number_bins(np);
-
- h2[lag] = nonlinvar(&buf[lag], y, np, nb);
-
- }
-
- }
-
-
- /* find maximum r2 and corresponding delay */
-
- max = r2[0];
- for(i=1; i<max_lag; i++)
- if(r2[i] > max) {max = r2[i]; j = i;}
-
- if(delay < 0) j = -j;
-
- printf("\nTrue delay = %d; maximum r2 = %f \
- found @ sample %d\n",
- delay, max, j);
-
-
- /* find maximum h2 and corresponding delay */
-
- max = h2[0];
- for(i=1; i<max_lag; i++)
- if(h2[i] > max) {max = h2[i]; j = i;}
-
- if(delay < 0) j = -j;
-
- printf("\nTrue delay = %d; maximum h2 = %f \
- found @ sample %d\n",
- delay, max, j);
-
-
- }
-
-
-
- /* compute number of bins for nonlinear variance calc. */
-
- int number_bins(int x)
- {
-
- int y;
-
- if(x < 129) y = NBINS - 4;
- else
- if(x < 257) y = NBINS - 3;
- else
- if(x < 513) y = NBINS - 2;
- else y = NBINS;
-
- return y;
-
- }
-
-
-
- /* routine to compute linear variance measure */
-
- double linvar(double *y, double *x, int nn)
- {
-
- register int j;
-
- double z, smx, smy, sqx, sqy, sxy, corr;
- double sqrt(), varx, vary, cov, nnn;
-
-
-
- /* initialize values */
-
- nnn = (double)nn;
-
- corr = sqy = 0.0;
-
-
- smx = 0.0;
- smy = 0.0;
- sqx = 0.0;
- sxy = 0.0;
-
- for(j=0; j<nn; j++) {
-
- smx += x[j];
- smy += y[j];
- sqx += (x[j] * x[j]);
- sxy += (x[j] * y[j]);
-
-
- sqy += (y[j] * y[j]);
-
-
- } /* end for */
-
- /* Compute covariance and variances */
-
- cov = (nnn * sxy) - (smx * smy);
- varx = (nnn * sqx) - (smx * smx);
-
-
-
- vary = (nnn * sqy) - (smy * smy);
-
- z = sqrt(varx * vary);
-
- if(z != 0.0) corr = cov / z;
- else corr = 0.0;
-
- return(corr*corr);
-
- }
-
-
-
- /* routine to compute nonlinear variance measure */
-
- int bin[NBINS][2*NMAX/NBINS];
- double q[NBINS], p[NBINS];
-
- double nonlinvar(double *x, double *y, int n, int nbins)
- {
-
- int i, j, k, l, index, index2, last;
-
- double min, max, range, width, hwidth, start, end,
- mean, mean2, totvar, unvar, s, f, h2, uu, offset;
-
-
- /* find max and min of x array */
-
- min = max = x[0]; last = 0;
-
- for(i=1; i<n; i++) {
- if(x[i] > max) {max = x[i]; last = i;}
- else
- if(x[i] < min) min = x[i];
- }
-
- range = max - min;
-
- width = range/(double)nbins;
-
- hwidth = width/2.0;
-
- for(i=0; i<nbins; i++) bin[i][0] = 0;
-
- /* get histogram of indexes */
-
- for(i=0; i<n; i++) {
- for(j=0; j<nbins; j++) {
- start = (double)j*width + min;
- end = start + width;
-
- if((x[i] >= start) && (x[i] < end)) {
- ++bin[j][0];
- bin[j][bin[j][0]] = i;
- break;
- }
- }
- }
-
- /* maximum x value (last one) */
-
- j = nbins-1;
- ++bin[j][0];
- bin[j][bin[j][0]] = last;
-
-
- /* compute x-midpoints and y average amplitudes */
-
- mean2 = 0.0;
- offset = hwidth + min;
-
- for(i=0; i<nbins; i++) {
-
- /* x value midpoints for each bin */
-
- p[i] = ((double)i * width) + offset;
-
- /* corresponding y average amplitudes */
-
- mean = 0.0;
-
- for(k=1; k<=bin[i][0]; k++) mean += y[bin[i][k]];
-
- q[i] = mean/(double)bin[i][0];
- mean2 += mean;
-
- }
-
-
- mean = mean2/(double)n; /* overall */
-
-
-
- /* compute h*h coefficient */
-
- /* first compute total variance of y */
-
- totvar = 0.0;
- for(i=0; i<n; i++) {
- s = y[i] - mean;
- totvar += (s * s);
- }
-
- /* compute total unexplained variance of y */
-
- unvar = 0.0;
- for(i=0; i<n; i++) {
-
- /* find f(x[i]), the nonlinear value */
-
- for(j=1; j<nbins-1; j++) {
- if(x[i] <= p[j]) {
- index = j-1;
- goto out1;
- }
- }
-
- index = nbins-2;
-
- out1:
- index2 = index++;
-
- f = ((q[index2] - q[index])/
- (p[index2] - p[index])) *
- (x[i] - p[index]) + q[index];
-
- uu = y[i] - f;
- unvar += (uu * uu);
-
- }
-
- /* now compute nonlinear regression coefficient */
-
-
- h2 = 1.0 - (unvar/totvar);
-
- return h2;
-
- }
-
-
-
-